#include <Timer.h>
#include "pingpong.h"
module pingpongC
{
	uses interface Boot;
	uses interface Leds;
	uses interface Timer < TMilli > as Timer0;

	uses interface Timer < TMilli > as Alarm;

	uses interface Packet;
	uses interface AMPacket; //what is used for???
	uses interface AMSend;
	uses interface SplitControl as AMControl;
	uses interface Receive;
	//uses interface Alarm<TMilli,uint32_t>;

}
implementation
{
	//init variables
	uint8_t counter = 0;
	bool haveball = TRUE;
	bool busy = FALSE;
	message_t ball;
	uint32_t time=0;//time for each pingpong
	uint32_t timeStart=0;
	uint32_t timeStop=0;

	event void Boot.booted ()
	{
		dbg ("Boot", "Boot execute\n");
		call AMControl.start ();
		call Alarm.startPeriodic(TIMER_PERIODIC_MILLI);
	}
	event void Alarm.fired()
	{
		//call Alarm.startPeriodic(1000);
		dbg ("pingpongC", "Alarm fired\n");
	}
  
//timer fired: Counter++, send ball if have ball
	event void Timer0.fired ()
	{
		dbg("Timer0","Timer fired\n");
		counter++;
		if (haveball) 
		{
			if (!busy)//AMsned busy?
			{
				pingpongMess *messagePacked = (pingpongMess *) (call Packet.getPayload (&ball, NULL));
				dbg ("Timer0", "Not busy\n");
				messagePacked->nodeid = TOS_NODE_ID;
				messagePacked->counter = counter;
				messagePacked->time = time;
				if (call AMSend.send (AM_BROADCAST_ADDR, &ball,sizeof (pingpongMess)) == SUCCESS)
//if AMsned can be used: set alarm (counting start when ping)
//if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS)
				{
					dbg ("Timer0", "Send ball\n");
					busy = TRUE;
					timeStart=call Alarm.getNow();
					dbg ("Timer0", "Alarm start=%i\n",timeStart);
				}
			}			
		}
	}
//SendDone: un lock the AMsend
	event void AMSend.sendDone (message_t * msg, error_t error)
	{
		dbg ("AMSend", "Send is done\n");
		if (&ball == msg)//test if the packet sent is the right one (AMsned maybe used by other component)
		{
			busy = FALSE;
			haveball=FALSE;
		}
	}

//AM control started: set timer
	event void AMControl.startDone (error_t err)
	{
		dbg ("AMControl", "AMControl start is done\n");
		if (err == SUCCESS)
		{
			dbg ("AMControl", "with SUCCESS\n");
			call Timer0.startOneShot(1);
		}
		else
		{
			dbg ("AMControl", "with FAILURE\n");
			call AMControl.start ();
		}
	}



  event void AMControl.stopDone (error_t err)
  {
    dbg ("AMControl", "AMControl stop is done\n");
  }
//ball receive: haveball=TRUE, update counter, take time Stop and calcule timepingpong
  event message_t *Receive.receive (message_t * msg, void *payload, uint8_t len)
  {
    dbg ("Receive", "Ball received\n");
    if (len == sizeof (pingpongMess))//neu nhan duoc day du
      {
		pingpongMess *messagePacked = (pingpongMess *) payload;
		haveball=TRUE;
		counter= messagePacked->counter;
		call Leds.set (counter);
		dbg ("Receive", "counter=%i\n",counter);
		call Timer0.startOneShot(TIMER_ONESHOT_MILLI);
		//when ball received: get the timeStop on alarm
		timeStop=call Alarm.getNow();
		dbg ("Receive", "timeStop = %i\n",timeStop);
		if (timeStop<timeStart)
		{
			time= TIMER_PERIODIC_MILLI-timeStart+timeStop;
		}else{time = timeStop - timeStart;}
		dbg ("Receive", "time do pingpong = %i\n",time);
      }
    return msg;
  }

}
